﻿using System;
using System.ComponentModel;
using System.Deployment.Application;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Threading;
using Antix.Mail.Smtp.Impostor.Client.Properties;

namespace Antix.Mail.Smtp.Impostor.Client
{
    /// <summary>
    ///   Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : IStatusParent
    {
        public MainWindow()
        {
            InitializeComponent();

            #region notify icon

            _notifyIcon = new NotifyIcon
            {
                Icon = Properties.Resources.LogoIcon,
                Visible = true
            };
            _notifyIcon.Click += (sender, e) =>
            {
                Show();
                WindowState = _windowState;
            };

            #endregion

            App.Status = new Status(this, StatusControl, _notifyIcon);

            try
            {
                App.Server = new Server();
                if (!Settings.Default.Hosts.Any())
                {
                    // always add a default
                    Settings.Default.Hosts.Add(
                        new HostConfiguration
                        {
                            IPAddress = IPAddress.Any,
                            Port = 25,
                            MessageStorage = new FileMessageStorageConfiguration()
                        });
                }
                Settings.Default.Save();

                Action showHideClose = () =>
                {
                    // only show remove if more than one
                    ((HostTabItem) HostsControl.Items[0]).HostCloseImage.Visibility =
                        HostsControl.Items.Count == 2
                            ? Visibility.Collapsed
                            : Visibility.Visible;
                };

                Func<HostConfiguration, HostTabItem> addHost
                    = hostConfig =>
                    {
                        var host = App.Server.CreateHost(hostConfig);
                        var hostTab = new HostTabItem(host, hostConfig);

                        HostsControl.Items.Insert(
                            HostsControl.Items.Count - 1, hostTab);

                        host.Event
                            += (sender, e) => HandleHostEvent(host, e);

                        hostTab.HostCloseImage.MouseUp
                            += (sender, e) =>
                            {
                                Settings.Default.Hosts.Remove(hostConfig);
                                Settings.Default.Save();

                                App.Server.RemoveHost(host);
                                host.Stop();

                                HostsControl.Items.Remove(hostTab);
                                showHideClose();

                                if (
                                    HostsControl.SelectedIndex
                                    == HostsControl.Items.Count - 1)
                                {
                                    HostsControl.SelectedIndex--;
                                    // move to previous
                                }
                            };

                        return hostTab;
                    };

                // add the new host tab
                HostsControl.Items.Add(new HostTabItem(addHost));

                // create hosts for each Model
                foreach (var hostConfig in Settings.Default.Hosts)
                {
                    addHost(hostConfig);
                }

                showHideClose();

                if (App.Server.Hosts.Any(h => h.Status == HostStates.Error))
                {
                    App.Status.Set(States.Error, Properties.Resources.Start_Failure_Message);
                }
                else
                {
                    App.Status.Set(States.Info, Properties.Resources.Start_Success_Message);
                }

                // show the version
                Title += " " + (
                             ApplicationDeployment.IsNetworkDeployed
                                 ? ApplicationDeployment.CurrentDeployment.CurrentVersion
                                 : GetType().Assembly.GetName().Version
                         ).ToVersionString();

                OpenConfigButton.Click += (sender, e) =>
                {
                    if (File.Exists(Settings.Default.Path))
                        Process.Start(Settings.Default.Path);
                };
            }
            catch (Exception ex)
            {
                Status.Log(ex);
            }
        }

        void HandleHostEvent(Host host, HostEventArgs e)
        {
            Dispatcher.Invoke(
                DispatcherPriority.Normal,
                (Action) (() =>
                {
                    switch (e.Type)
                    {
                        default:
                            return;
                        case HostEventTypes.SessionMessageReceived:
                            App.Status.Set(
                                States.Info,
                                Properties.Resources.
                                    MessageReceived_Message,
                                e.Session);

                            break;
                        case HostEventTypes.Started:
                            App.Status.Set(
                                States.Info,
                                Properties.Resources.Host_Started_Message,
                                host,
                                host.IPAddress,
                                host.Port);

                            break;
                        case HostEventTypes.Stopped:
                            App.Status.Set(
                                States.Info,
                                Properties.Resources.Host_Stopped_Message,
                                host,
                                host.IPAddress,
                                host.Port);

                            break;
                    }
                }));
        }

        #region window

        NotifyIcon _notifyIcon;
        WindowState _windowState = WindowState.Normal;

        protected override void OnStateChanged(EventArgs e)
        {
            base.OnStateChanged(e);

            if (WindowState == WindowState.Minimized) Hide();
            else _windowState = WindowState;
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            if (App.Server != null) App.Server.Dispose();
            _notifyIcon?.Dispose();

            App.Server = null;
            _notifyIcon = null;
        }

        #endregion
    }
}